package com.common.sdk.net.download.callback;

import java.util.ArrayList;
import java.util.List;

import android.os.Handler;
import android.os.Looper;

import com.common.sdk.net.download.callback.error.CallbackEnum;
import com.common.sdk.net.download.callback.interfaces.IDownloadCallback;
import com.common.sdk.net.download.callback.interfaces.IResponseDelivery;
import com.common.sdk.net.download.db.ControlCacheAndDb;
import com.common.sdk.net.download.db.DownloadSQLiteOpenHelper;
import com.common.sdk.net.download.request.model.DownloadInfo;
import com.common.sdk.net.download.util.DownloadLog;

public class CallbackObservable {

    protected List<IDownloadCallback> observers = new ArrayList<IDownloadCallback>();
    private final IResponseDelivery mDelivery;

    private static class BaseObservableHolder {
        static final CallbackObservable instance = new CallbackObservable();
    }

    public static CallbackObservable getIntence() {
        return BaseObservableHolder.instance;
    }

    private CallbackObservable() {
        mDelivery = new ExecutorDelivery(new Handler(Looper.getMainLooper()));
    }

    public void registerObserver(IDownloadCallback iDownloadCallback) {
        if (iDownloadCallback == null) {
            throw new NullPointerException("registerObserver is null");
        }
//        long time1 = System.currentTimeMillis();
        if (!observers.contains(iDownloadCallback)) {
//            long time2 = System.currentTimeMillis();
//            DownloadLog.debug("CallbackObservableTime " + (time2 - time1));
            observers.add(iDownloadCallback);
//            long time3 = System.currentTimeMillis();
//            DownloadLog.debug("CallbackObservableTime " + (time3 - time2));
            synchronized (DownloadSQLiteOpenHelper.class) {
                mDelivery.postResponse(iDownloadCallback, CallbackEnum.INITIALIZATION_SUCCESS,
                        ControlCacheAndDb.getAllDownloadList());
            }
//            long time4 = System.currentTimeMillis();
//            DownloadLog.debug("CallbackObservableTime " + (time4 - time3));
        }
    }

    public void removeObserver(IDownloadCallback observer) {
        observers.remove(observer);
    }

    public void removeAllObservers() {
        observers.clear();
    }

    public void notifyObservers(CallbackEnum callbackEnum, DownloadInfo downloadInfo) {
        int size = 0;
        IDownloadCallback[] arrays = null;
        size = observers.size();
        arrays = new IDownloadCallback[size];
        observers.toArray(arrays);
        if (arrays != null) {
            synchronized (DownloadSQLiteOpenHelper.class) {
                for (IDownloadCallback observer : arrays) {
                    update(observer, callbackEnum, downloadInfo);
                }
            }
        }
    }

    public void notifyObservers(CallbackEnum callbackEnum, List<DownloadInfo> list) {
        int size = 0;
        IDownloadCallback[] arrays = null;
        size = observers.size();
        arrays = new IDownloadCallback[size];
        observers.toArray(arrays);
        if (arrays != null) {
            synchronized (DownloadSQLiteOpenHelper.class) {
                for (IDownloadCallback observer : arrays) {
                    update(observer, callbackEnum, list);
                }
            }
        }
    }

    public void notifyObservers(int downloadFailedState, CallbackEnum callbackEnum,
                                DownloadInfo downloadInfo) {

        int size = 0;
        IDownloadCallback[] arrays = null;
        size = observers.size();
        arrays = new IDownloadCallback[size];
        observers.toArray(arrays);
        if (arrays != null) {
            synchronized (DownloadSQLiteOpenHelper.class) {
                for (IDownloadCallback observer : arrays) {
                    update(observer, downloadFailedState, callbackEnum, downloadInfo);
                }
            }
        }
    }

    private void update(IDownloadCallback iDownloadCallback, int downloadFailedState, CallbackEnum callbackEnum,
                        DownloadInfo downloadInfo) {
        mDelivery.postResponse(iDownloadCallback, downloadFailedState, callbackEnum, downloadInfo);
    }

    private void update(IDownloadCallback iDownloadCallback, CallbackEnum callbackEnum, DownloadInfo downloadInfo) {
        mDelivery.postResponse(iDownloadCallback, callbackEnum, downloadInfo);
    }

    @SuppressWarnings("unused")
    private void update(IDownloadCallback iDownloadCallback, int downloadFailedState, CallbackEnum callbackEnum,
                        List<DownloadInfo> list) {
        mDelivery.postResponse(iDownloadCallback, downloadFailedState, list);
    }

    private void update(IDownloadCallback iDownloadCallback, CallbackEnum callbackEnum, List<DownloadInfo> list) {
        mDelivery.postResponse(iDownloadCallback, callbackEnum, list);
    }

}
